/*
 * $Id: XLIWriter.cc,v 1.4 2006-02-10 05:01:08 bacon Exp $
 */

#include <xpp/xli/XLIWriter.h>
#include <xp/bas/assert.h>

#define WRITE_CHAR(c) \
	do { if (write_char(c) == -1) return XP_NULL; } while(0)

#define WRITE_CHAR_ESCAPE(c) \
	do { if (write_char_escape(c) == -1) return XP_NULL; } while(0)

#define WRITE_STR(c) \
	do { if (write_str(c) == -1) return XP_NULL; } while(0)

#define WRITE_STR_ESC(c,len) \
	do { if (write_str_escape(c) == -1) return XP_NULL; } while(0)

#define WRITE_STR_ESCLEN(c,len) \
	do { if (write_str_escape(c,len) == -1) return XP_NULL; } while(0)


namespace xpp
{
	namespace xli
	{

		XLIWriter::XLIWriter ()
		{
		}

		XLIWriter::~XLIWriter ()
		{
		}

		XLI* XLIWriter::write (XLI* xli)
		{
			return write_xli (xli, 0);
		}

		XLI* XLIWriter::write_xli (XLI* xli, xp_size_t tabs)
		{
			xp_size_t i;
			XLICell* p = xli->head();
		
			while (p != XP_NULL) {
				for (i = 0; i < tabs; i++) {
					WRITE_CHAR (XP_CHAR('\t'));
				}
				
				XLIKey* key = p->key();
				XLIVal* val = p->val();
				xp_assert (key != XP_NULL && val != XP_NULL);
		
				WRITE_STR (key->data());
				WRITE_STR (XP_TEXT(" = "));

				if (val->isStr()) {
					WRITE_CHAR (XP_CHAR('\''));
					WRITE_STR_ESCLEN (((XLIStr*)val)->data(), ((XLIStr*)val)->size());
					WRITE_CHAR (XP_CHAR('\''));
					WRITE_CHAR (XP_CHAR(';'));
				}
				else {
					WRITE_STR (XP_TEXT("{\n"));
					if (write_xli ((XLI*)val, tabs + 1) == XP_NULL) 
						return XP_NULL;

					for (i = 0; i < tabs; i++) {
						WRITE_CHAR (XP_CHAR('\t'));
					}
					WRITE_CHAR (XP_CHAR('}'));
				}
		
				WRITE_CHAR (XP_CHAR('\n'));
				p = p->cdr();
			}

			return xli;
		}

		int XLIWriter::write_str (const xp_char_t* str)
		{
			while (*str != XP_CHAR('\0')) {
				if (write_char(*str) == -1) return -1;
				str++;
			}	

			return 0;
		}

		int XLIWriter::write_str_escape (const xp_char_t* str)
		{
			while (*str != XP_CHAR('\0')) {
				if (write_char_escape(*str) == -1) return -1;
				str++;
			}	

			return 0;
		}

		int XLIWriter::write_str_escape (const xp_char_t* str, xp_size_t len)
		{
			const xp_char_t* end = str + len;

			while (str < end) {
				if (write_char_escape(*str) == -1) return -1;
				str++;
			}	

			return 0;
		}

		int XLIWriter::write_char (xp_char_t c)
		{
			int n;
			
			n = writeChar(c);
			if (n <= 0) return -1;

			return 0;
		}

		int XLIWriter::write_char_escape (xp_char_t c)
		{
			int n;

			if (c == XP_CHAR('\'')) {
				n = writeChar(XP_CHAR('\\'));
				if (n <= 0) return -1;
			}
			
			n = writeChar(c);
			if (n <= 0) return -1;

			return 0;
		}


	}
}
